package me.seawenc.db.migration.helper;


import com.alibaba.fastjson.JSON;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;

public class YmlHelper {

	/**
	 * 行分隔符
	 */
	private static final String LINE_SEPARATOR = "\n";

	/**
	 *
	 * @param ymlFileName
	 * @param prefix 属性前缀，只返回前缀是：prefix的属性
	 * @return
	 */
	public static Properties yamlFile2PropsFilter(String ymlFileName,String prefix) {
		// 获取文件数据
		String yml = read(ymlFileName);
		List<YmlNode> nodeList = getNodeList(yml).stream()
				.filter(node-> node.getKey().startsWith(prefix))
				// 删除前缀
				.peek(node-> node.setKey(node.getKey().replace(prefix,"")))
				.filter(node-> Optionalx.isPresent(node.getValue()))
				.collect(Collectors.toList());
		if(nodeList.isEmpty()){
			return new Properties();
		}
		return yamlNodeList2Props(nodeList);
	}


	/**
	 *
	 * @param ymlFileName
	 * @param prefix 属性前缀，只返回前缀是：prefix的属性
	 * @return
	 */
	public static String getConfig(String ymlFileName,String prefix) {
		Properties properties = yamlFile2PropsFilter(ymlFileName, prefix);
		if(properties.isEmpty()){
			return "";
		}
		if(properties.size()>1){
			throw new RuntimeException(prefix+":当前配置项下有子项:"+ JSON.toJSONString(properties));
		}
		return properties.values().stream().collect(Collectors.toList()).get(0)+"";
	}
	public static String getConfig(String ymlFileName,String prefix,String defValue) {
		return Optionalx.ofByDefGet(getConfig(ymlFileName, prefix), defValue);
	}

	/**
	 * 将yamlnodeList转为prop格式
	 * @param nodeList
	 * @return
	 */
	private static Properties yamlNodeList2Props(List<YmlNode> nodeList) {
		Properties props=new Properties();
		Arrays.stream(printNodeList(nodeList).split(LINE_SEPARATOR))
				.map(line-> line.trim())
				.filter(line-> Optionalx.isPresent(line))
				.filter(line-> !line.startsWith("#"))
				.filter(line-> line.contains("="))
				.forEach(l-> props.put(l.split("=")[0],l.substring(l.split("=")[0].length() + 1)));
		return props;
	}

	/**
	 * 读取文件行
	 * @return
	 */
	private static String read(String ymlFilePath) {
		File file = new File(ymlFilePath);
		if (!file.exists()&& file.isFile()) {
			throw new RuntimeException("配置文件： " + ymlFilePath + "不存在！！");
		}
		try (FileInputStream fis = new FileInputStream(file)) {
			byte[] b = new byte[(int) file.length()];
			fis.read(b);
			return new String(b, StandardCharsets.UTF_8);
		} catch (IOException e) {
			Log.error("输入输出流异常,msg:"+e.getMessage());
		}
		return "";
	}

	/**
	 * 将ymlnode转为可打印的格 式
	 * @param nodeList
	 * @return
	 */
	public static String printNodeList(List<YmlNode> nodeList) {
		StringBuilder sb = new StringBuilder();
		for (YmlNode node : nodeList) {
			if (node.getLast().equals(Boolean.FALSE)) {
				continue;
			}
			if (node.getEmptyLine().equals(Boolean.TRUE)) {
				sb.append(LINE_SEPARATOR);
				continue;
			}
			// 判断是否有行级注释
			if (node.getHeadRemark().length() > 0) {
				String s = "# " + node.getHeadRemark();
				sb.append(s).append(LINE_SEPARATOR);
				continue;
			}
			// 判断是否有行末注释 (properties中注释不允许末尾注释，故而放在上面)
			if (node.getTailRemark().length() > 0) {
				String s = "# " + node.getTailRemark();
				sb.append(s).append(LINE_SEPARATOR);
			}

			String kv = node.getKey() + "=" + node.getValue();
			sb.append(kv).append(LINE_SEPARATOR);
		}
		return sb.toString();
	}

	/**
	 * 获得节点列表
	 * @param yml
	 * @return
	 */
	private static List<YmlNode> getNodeList(String yml) {
		String[] lines = yml.split(LINE_SEPARATOR);
		List<YmlNode> nodeList = new ArrayList<>();
		Map<Integer, String> keyMap = new HashMap<>();
		Set<String> keySet = new HashSet<>();
		for (String line : lines) {
			YmlNode node = getNode(line);
			if (node.getKey() != null && node.getKey().length() > 0) {
				int level = node.getLevel();
				if (level == 0) {
					keyMap.clear();
					keyMap.put(0, node.getKey());
				} else {
					int parentLevel = level - 1;
					String parentKey = keyMap.get(parentLevel);
					String currentKey = parentKey + "." + node.getKey();
					keyMap.put(level, currentKey);
					node.setKey(currentKey);
				}
			}
			keySet.add(node.getKey() + ".");
			nodeList.add(node);
		}
		// 标识是否最后一级
		for (YmlNode each : nodeList) {
			each.setLast(getNodeLast(each.getKey(), keySet));
		}
		return nodeList;
	}

	/**
	 * 获得叶子节点
	 * @param key
	 * @param keySet
	 * @return
	 */
	private static boolean getNodeLast(String key, Set<String> keySet) {
		if (key.isEmpty()) {
			return true;
		}
		key = key + ".";
		int count = 0;
		for (String each : keySet) {
			if (each.startsWith(key)) {
				count++;
			}
		}
		return count == 1;
	}

	/**
	 * 获得所有节点
	 * @param line
	 * @return
	 */
	private static YmlNode getNode(String line) {
		YmlNode node = new YmlNode();
		// 初始化默认数据（防止NPE）
		node.setEffective(Boolean.FALSE);
		node.setEmptyLine(Boolean.FALSE);
		node.setHeadRemark("");
		node.setKey("");
		node.setValue("");
		node.setTailRemark("");
		node.setLast(Boolean.FALSE);
		node.setLevel(0);
		// 空行，不处理
		String trimStr = line.trim();
		if (trimStr.isEmpty()) {
			node.setEmptyLine(Boolean.TRUE);
			return node;
		}
		// 行注释，不处理
		if (trimStr.startsWith("#")) {
			node.setHeadRemark(trimStr.replaceFirst("#", "").trim());
			return node;
		}
		// 处理值
		String[] strs = line.split(":", 2);
		// 拆分后长度为0的，属于异常数据，不做处理
		if (strs.length == 0) {
			return node;
		}
		// 获取键
		node.setKey(strs[0].trim());
		// 获取值
		String value;
		if (strs.length == 2) {
			value = strs[1];
		} else {
			value = "";
		}
		// 获取行末备注
		String tailRemark = "";
		if (value.contains(" #")) {
			String[] vs = value.split("#", 2);
			if (vs.length == 2) {
				value = vs[0];
				tailRemark = vs[1];
			}
		}
		node.setTailRemark(tailRemark.trim());
		node.setValue(value.trim());
		// 获取当前层级
		int level = getNodeLevel(line);
		node.setLevel(level);
		node.setEffective(Boolean.TRUE);
		return node;
	}

	/**
	 * 获得节点层级
	 * @param line
	 * @return
	 */
	private static int getNodeLevel(String line) {
		if (line.trim().isEmpty()) {
			return 0;
		}
		char[] chars = line.toCharArray();
		int count = 0;
		for (char c : chars) {
			if (c != ' ') {
				break;
			}
			count++;
		}
		return count / 2;
	}

	/**
	 * YmlNode
	 */
	static class YmlNode {

		/**
		 * 层级关系
		 */
		private Integer level;

		/**
		 * 键
		 */
		private String key;

		/**
		 * 值
		 */
		private String value;

		/**
		 * 是否为空行
		 */
		private Boolean emptyLine;

		/**
		 * 当前行是否为有效配置
		 */
		private Boolean effective;

		/**
		 * 头部注释（单行注释）
		 */
		private String headRemark;

		/**
		 * 末尾注释
		 */
		private String tailRemark;

		/**
		 * 是否为最后一层配置
		 */
		private Boolean last;

		public Integer getLevel() {
			return level;
		}

		public void setLevel(Integer level) {
			this.level = level;
		}

		public String getKey() {
			return key;
		}

		public void setKey(String key) {
			this.key = key;
		}

		public String getValue() {
			return value;
		}

		public void setValue(String value) {
			this.value = value;
		}

		public Boolean getEmptyLine() {
			return emptyLine;
		}

		public void setEmptyLine(Boolean emptyLine) {
			this.emptyLine = emptyLine;
		}

		public Boolean getEffective() {
			return effective;
		}

		public void setEffective(Boolean effective) {
			this.effective = effective;
		}

		public String getHeadRemark() {
			return headRemark;
		}

		public void setHeadRemark(String headRemark) {
			this.headRemark = headRemark;
		}

		public String getTailRemark() {
			return tailRemark;
		}

		public void setTailRemark(String tailRemark) {
			this.tailRemark = tailRemark;
		}

		public Boolean getLast() {
			return last;
		}

		public void setLast(Boolean last) {
			this.last = last;
		}
	}
}



